package com.may.wlrj.finger;

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import javax.annotation.PostConstruct;

import org.apache.commons.codec.binary.Base64;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.may.wlrj.dao.UserDAO;
import com.may.wlrj.entity.FingerEntity;
import com.sun.jna.Native;

@Component
public class ZZFingerUtil {
	private Logger log = Logger.getLogger(ZZFingerUtil.class);
	public static ZZFingerUtil zzFingerUtil;
	private ZZFingerAbs instanceDll = null;
	private static final HashMap<String,String> userFingers;
	
	private UserDAO userDao;
	@Autowired
    public void setUserDao(UserDAO userDao){
        this.userDao =userDao;
    }
	
	static {
		userFingers = new HashMap<String,String>();
    }
	
	@PostConstruct
    public void init() {    
		zzFingerUtil = this;
    } 
	
	public void initJnaGX() {
    	String webRootPath = ZZFingerUtil.class.getResource("").getPath().replaceFirst("/", "");
    	String webInfPath = webRootPath.substring(0,webRootPath.indexOf("classes"));
    	String dllpath = webInfPath + "ID_Fpr.dll";
    	
    	
    	try {
    		instanceDll  = (ZZFingerAbs)Native.loadLibrary(dllpath,ZZFingerAbs.class);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			log.error("----------------->>>导入指纹库算法失败!");
		}
    	
    	initUserFingers();
    	
	}
	
	public void initUserFingers() {
		List<FingerEntity> fingers = userDao.findFingers();
		if(fingers != null) {
			userFingers.clear();
			for(FingerEntity finger : fingers) {
				
				userFingers.put(finger.getUsername()+"-"+finger.getFingerflag(), finger.getFingerbase());
			}
			
		}
	}
	
	public void AdduserFinger(String key,String fingerbase) {
		userFingers.put(key, fingerbase);
	}
	
	public void DeluserDetail(String key) {
		userFingers.remove(key);
	}
	
	private float fingerMatch(byte[] finger1,byte[] finger2) {
		//String webRootPath = ZZFingerUtil.class.getResource("").getPath().replaceFirst("/", "");
    	//String webInfPath = webRootPath.substring(0,webRootPath.indexOf("classes"));
    	//String strMr210path = webInfPath + "MR210Templete.dat";
    	//String str66k3path = webInfPath + "66k3Templete.dat";
		//String xx1 = "QwESDgFjNf///////////////ykArQAAAAAAAAAAAJwckPwzN7L8klI+/oJUk/xEXGT+V2+l/KBzNv6xcoL8PYnH/IWHMv6ijYX8PKnY/EO4L/5Hsyv+pbl7/NWzbvzQym38lcgi/j7PHv7H1V78seOB/DHhGf6s5DD+DuUM/qX1Fv6c9mP8sgQY/2wFIP9HEyH/ng5Z/VYbcP2BHG79PDUT/04zaf0zOmf9mjx7/YRJiv0sTmD9SlAd/xFYd/0vXHL9AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIg=";
		//String xx2 = "QwESDgFjM////////////////zEAzQAAAAAAAAAAAHoUtvxBK8381i0+/oQuWP7MNZP8mEuh/ONRNv6AYLn8zGg1/hhs+PzjcH/8OHzq/BmGTvx5gdf8IIc8/IGJM/4ck038w5IW/uSfd/x4oRT+xKVj/NWiIf4tqfH8L7j7/E28Cv5tthD+58Qv/urAePwa4QL+peEa/n/nGP7Z7FD8i/Fn/Lf4avxwChD/gwlm/WcSYv2PFB3/YShf/XojEv+2JoP9QSxz/Vo4Z/0VN4j9Qjx8/TNBhf1BS3v9DU6J/UBVkf0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAc=";
		//byte[] x1 = Base64.decodeBase64(xx1);
		//byte[] x2 = Base64.decodeBase64(xx2);
		//byte[] x1 = ReadData(strMr210path);
		//byte[] x2 = ReadData(str66k3path);
		float[] pfSimilscore= new float[1];
		instanceDll.FP_FeatureMatch_Encrypt(finger1, finger2, pfSimilscore);
		return pfSimilscore[0];
	}
	
	public String find(byte[] fingerbase) {
	    String match = "";
	    float high = 0;
	    Iterator<Map.Entry<String, String>> entries = userFingers.entrySet().iterator();
	    while (entries.hasNext()) {
	    	 
	    	Map.Entry<String, String> entry = entries.next();
	    	float score = fingerMatch(Base64.decodeBase64(entry.getValue()), fingerbase);
	        if (score > high) {
	            high = score;
	            match = entry.getKey();
	        }
	    }
	    return high >= 0.3f ? match : "";
	}
	
	public static byte[] base64String2ByteFun(String base64Str){
        return Base64.decodeBase64(base64Str);
    }
    //byte[]转base64
    public static String byte2Base64StringFun(byte[] b){
        return Base64.encodeBase64String(b);
    }
    
    public int getUnsignedByte (byte data){      //将data字节型数据转换为0~255 (0xFF 即BYTE)。
        return data&0xFF;
     }
    
    public byte[] ReadData(String filepath) {
        File f = new File(filepath);
        if (!f.exists()) {
            return null;
        }
        ByteArrayOutputStream bos = new ByteArrayOutputStream((int) f.length());
        BufferedInputStream in = null;
        try {
            in = new BufferedInputStream(new FileInputStream(f));
            int buf_size = 512;
            byte[] buffer = new byte[buf_size];
            int len = 0;
            while (-1 != (len = in.read(buffer, 0, buf_size))) {
                bos.write(buffer, 0, len);
            }
            return bos.toByteArray();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                bos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }
    
    public byte[] hexStr2Byte(String hex) {
        ByteBuffer bf = ByteBuffer.allocate(hex.length() / 2);
        for (int i = 0; i < hex.length(); i++) {
            String hexStr = hex.charAt(i) + "";
            i++;
            hexStr += hex.charAt(i);
            byte b = (byte) Integer.parseInt(hexStr, 16);
            bf.put(b);
        }
        return bf.array();
    }
    
    public byte[] hexStringToBytes(String hexString) {   
        if (hexString == null || hexString.equals("")) {   
            return null;   
        }   
        hexString = hexString.toUpperCase();   
        int length = hexString.length() / 2;   
        char[] hexChars = hexString.toCharArray();   
        byte[] d = new byte[length];   
        for (int i = 0; i < length; i++) {   
            int pos = i * 2;   
            d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));   
        }   
        return d;   
    }  
    
    private byte charToByte(char c) {   
        return (byte) "0123456789ABCDEF".indexOf(c);   
    } 
}
